package aleksandar.djuric.entities;

import java.awt.Color;
import java.awt.FontMetrics;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

import javax.swing.JTree;

import aleksandar.djuric.common.TimeManagement;


public class Player implements Comparable<Player>{
	public static final String attribNames[] = 
		{
		// Physical
		"Jumping","Strength","Balance","Accel.","Agility","Speed","Stamina",
		// Technical
		"Ball Cont.","One touch","Tackling","Dribble","High Pas.","Low Pas.",
		"Curving","Blocking",
		// Mental
		"Scor. Pos.","Anticipation","Def. Pos.","Vision","Fearl.",
		// Finishing
		"Heading","Sh. Acc.","Shoot. Str.",
		// Keeper
		"Aerial Ab.","Keep. Pos.","Reflexes","Handling","P. w. Hands"
		};
	
	public static final String specialAbilities[] =
	{
		"Maradona Pass", "Step-over Dribble", "Bicycle Kick", "Ball Cover",	
		"Sliding Tackle", "Hollywood Dive", "Zidane Reception",	
		"Airspace Clearing", "Chip Shot", "Beckham Cross", "Split-Vision Pass",
		"360 Dribble", "Kamikaze Block", "Shirt Pull", "Superman Punch",
		"Lightning Save", "Airspace Interception"
	};
	public static final HashMap<String, Integer> positions = 
									new HashMap<String, Integer>();
	static
	{
		positions.put("GK", 0);
		positions.put("CD", 1);
		positions.put("SD", 2);
		positions.put("DCM", 3);
		positions.put("CM", 4);
		positions.put("SM", 5);
		positions.put("ACM", 6);
		positions.put("WF", 7);
		positions.put("CF", 8);
	}
		
	
	public static final int ACTIVE = 0,
							CASUAL = 1,
							INACTIVE = 2,
							NO_USER = 3;
	public static final int firstAttribID = 761209;
	public static final int PHYSICAL = 0;
	public static final int TECHNICAL = 7;
	public static final int MENTAL = 15;
	public static final int FINISHING = 20;
	public static final int KEEPER = 23;
	public static final int N_ATTRIBS = 28;
	public static String nL = System.getProperty("line.separator");
	private static final SimpleDateFormat dateFormat = 
		new SimpleDateFormat("dd/MM/yyyy");
	private static final SimpleDateFormat formatLastOnline =
		new SimpleDateFormat("dd/MM/yyyy HH:mm");
	
	public static final FontMetrics metrics;
	public static final int spaceWidth;
	public static final int numberWidth;
	public static final int positionWidth;
	static
	{
		JTree jTree = new JTree();
		metrics = jTree.getFontMetrics(jTree.getFont());
		spaceWidth = metrics.stringWidth(" ");
		numberWidth = metrics.stringWidth("00 ");
		positionWidth = metrics.stringWidth("MMM ");
	}
	private String name;
	private Date birthDate;
	private int age;
	private String position;
	private String aPosition;
	private Double value;
	private int number;
	private Date lastOnline;
	private Attribute attribs[];
	private int id;
	private String userName;
	private double power;
	private double power51;
	private boolean online;
	private boolean myChar;
	private int activity = INACTIVE;
	private HashMap<String, Integer> playerSpecialAbilities;
	private static final URL star = 
		Player.class.getResource("/images/FilledStar.png");

	public Player(String name, String birthDate){
		this();
		this.name = name;
		this.birthDate = makeDate(birthDate);
	}
	
	public Player()
	{
		attribs = new Attribute[0];
		playerSpecialAbilities = new HashMap<String, Integer>();
	}
	
	public Player(int number, int id, String name, String position,
			String aPosition, int age, double value)
	{
		this();
		this.number = number;
		this.id = id;
		this.name = name;
		this.position = position;
		this.aPosition = aPosition;
		this.age = age;
		this.value = value;
		userName = "No user";
		power = 0;
		power51 = 0;
	}
	
	private static Date makeDate(String date)
	{
		try {
			return dateFormat.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
			return new Date(0);
		}
	}

	

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Player other = (Player) obj;
		if (id != other.id)
			return false;
		return true;
	}

	public Attribute[] getAttribs() {
		return attribs;
	}


	public void setAttribs(Attribute[] attribs) {
		this.attribs = attribs;
		power = 0;
		power51 = 0;
		double curAttrib = 0;
		for (int i = 0; i < attribs.length; i++) {
			curAttrib = attribs[i].getTrueValue();
			if(curAttrib == 0)
				curAttrib = (attribs[i].getMax() + attribs[i].getMin()) / 2;
			if(curAttrib > 51)
				power51 += curAttrib - 51;
			power += curAttrib;
		}
	}
	
	public void addSpecialAbility(String sA, int value)
	{
		playerSpecialAbilities.put(sA, value);
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setBirthDate(String birthDate) {
		this.birthDate = makeDate(birthDate);
	}
	
	public void setUserName(String userName)
	{
		this.userName = userName;
	}
	
	public String getUserName()
	{
		return userName;
	}


	public int getNumber() {
		return number;
	}


	public void setNumber(int number) {
		this.number = number;
	}


	public int getAge() {
		return age;
	}


	public void setAge(int age) {
		this.age = age;
	}


	public double getValue() {
		return value;
	}


	public void setValue(double value) {
		this.value = value;
	}


	public Date getLastOnline() {
		return lastOnline;
	}


	public void setLastOnline(Date lastOnline) {
		this.lastOnline = lastOnline;
		Calendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		
		c.add(Calendar.DATE, -1);
		if(lastOnline.after(c.getTime()))
			activity = ACTIVE;
		else
		{
			c.add(Calendar.DATE, -6);
			if(lastOnline.after(c.getTime()))
				activity = CASUAL;
			else if(lastOnline.equals(new Date(0)))
				activity = NO_USER;
			else
				activity = INACTIVE;
		}
	}


	public String getName() {
		return name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Date getBirthDate() {
		return birthDate;
	}

	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}

	public String getaPosition() {
		return aPosition;
	}

	public void setaPosition(String aPosition) {
		this.aPosition = aPosition;
	}

	public void setBirthDate(Date birthDate) {
		this.birthDate = birthDate;
	}
	
	public long getPower() {
		return Math.round(power);
	}

	public long getPower51() {
		return Math.round(power51);
	}

	public boolean isOnline() {
		return online;
	}

	public void setOnline(boolean online) {
		this.online = online;
	}

	public boolean isMyChar() {
		return myChar;
	}

	public void setMyChar(boolean myChar) {
		this.myChar = myChar;
	}

	public int getActivity() {
		return activity;
	}
	
	@Override
	public String toString() {
		int length = metrics.stringWidth(Integer.toString(getNumber()));
		length = numberWidth - length;
		length = (int) Math.round(length / (double)spaceWidth);
		StringBuilder s = new StringBuilder();
		s.append(getNumber());
		for (int i = 0; i < length; i++) {
			s.append(" ");
		}
		
		s.append(position);
		length = metrics.stringWidth(position);
		length = positionWidth - length;
		length = (int) Math.round(length / (double)spaceWidth);
		for (int i = 0; i < length; i++) {
			s.append(" ");
		}
		
		s.append(getName());
		return s.toString();
	}
	

	public String toStringStatistic() {
		StringBuilder s = new StringBuilder();
		s.append(getNumber());
		s.append(",");
		s.append(getName());
		s.append(",");
		s.append(Math.round(power));
		s.append(",");
		s.append(Math.round(power51));
		return s.toString();
	}

	
	public String toStringFull() {
		String blanks = "                  ";
		StringBuilder builder = new StringBuilder();
		builder.append("Player");
		builder.append(blanks.substring(6) + name + " " + id + nL);
		if(isMyChar())
		{
			builder.append("My Character");
			builder.append("," + TimeManagement.getTM().getString(lastOnline));
			builder.append("," + TimeManagement.getTM().getNextTrainingDate());
		}
		else
		{
			builder.append(TimeManagement.getTM().getString(lastOnline));
		}
		builder.append(nL + "birthDate");
		builder.append(blanks.substring(9) + 
				((birthDate != null)?
						dateFormat.format(birthDate)
						: "Unknown")
						);		
		builder.append(nL + "userName");
		builder.append(blanks.substring("userName".length()) + userName);
		builder.append(nL + "age");
		builder.append(blanks.substring(3) + age);
		builder.append(nL + "position");
		builder.append(blanks.substring(8) + position);
		builder.append(nL + "aPosition");
		builder.append(blanks.substring(9) + aPosition);
		builder.append(nL + "value");
		builder.append(blanks.substring(5) 
				+ ((value != null) ? value.intValue() : null));
		builder.append(nL + "number");
		builder.append(blanks.substring(6) + number);
//		builder.append(nL + "lastOnline");
//		builder.append(blanks.substring(10) + 
//				((lastOnline != null)?
//						dateFormat.format(lastOnline)
//						: "Unknown")
//						);	
//		builder.append(nL + nL + "attributes:");
		for (int i = 0; i < attribs.length; i++) {
			switch (i)
			{
			case PHYSICAL:
				builder.append(nL + "--------\tphysical\t-------");
				break;
			case TECHNICAL:
				builder.append(nL +"--------\ttechnical\t-------");
				break;
			case MENTAL:
				builder.append(nL +"--------\tmental\t-------");
				break;
			case FINISHING:
				builder.append(nL +"--------\tfinishing\t-------");
				break;
			case KEEPER:
				builder.append(nL +"--------\tkeeper\t-------");
				break;
			default:
				break;
			}
				
			
			builder.append(nL + attribNames[i] 
			        + blanks.substring(attribNames[i].length())
					+ attribs[i].toStringFile());
			
		}
		if(!playerSpecialAbilities.isEmpty())
		{
			builder.append(nL);
			builder.append(nL);
			builder.append("special abilities" + nL);
			for (Map.Entry<String, Integer> entry : 
				playerSpecialAbilities.entrySet()) 
			{
				builder.append(entry.getKey());
				builder.append("_");
				builder.append(entry.getValue());
				builder.append(nL);
			}
		}
		return builder.toString();
	}
	
	public String table()
	{
		return 
		"<table " +
		"border=\"0\"" +
		"cellspacing=\"0\"" +
		"cellpadding=\"0\"" +
		"align=\"center\"" +
		"width=\"95%\"" +
		"style=\"" +
		"font-weight: bold;" +
		"font-family:sans-serif;" +
		"font-size: 12" +
		"\">";
	}
	
	public String toStringDisplay() {
		StringBuilder builder = new StringBuilder();
		builder.append(table());
			builder.append("<tr align=\"left\">");
				builder.append("<td>");
					builder.append(userName);
				builder.append("</td>");
				
				builder.append("<td>");
					builder.append(name + " " + id);
				builder.append("</td>");
			builder.append("</tr align=\"left\">");
			builder.append("<tr>");
				builder.append("<td>");
					builder.append("lastOnline");
				builder.append("</td>");
				
				builder.append("<td style=\"color:" +
						(Integer.toHexString(
								getActivityColor().getRGB()).substring(2)) +
						"\" >");
				
					builder.append(
							((lastOnline != null)?
								(
									(lastOnline.equals(new Date(0)))?"No user":
										formatLastOnline.format(lastOnline)
								):
								"Unknown")
							);	
					builder.append("</td>");
			builder.append("</tr>");
			builder.append("<tr>");
				builder.append("<td>");
					builder.append("age");
				builder.append("</td>");
					
				builder.append("<td>");
					builder.append(age);
				builder.append("</td>");
			builder.append("</tr>");
			builder.append("<tr>");
				builder.append("<td>");
					builder.append("position");
				builder.append("</td>");
				builder.append("<td>");
					builder.append(position);
				builder.append("</td>");
			builder.append("</tr>");
			builder.append("<tr>");
				builder.append("<td>");
					builder.append("aPosition");
				builder.append("</td>");
				builder.append("<td>");
					builder.append(aPosition);
				builder.append("</td>");
			builder.append("</tr>");
			builder.append("<tr>");	
				builder.append("<td>");
					builder.append("value");
				builder.append("</td>");
				builder.append("<td>");
					builder.append(
							((value != null) ? value.intValue() : null));
				builder.append("</td>");
			builder.append("</tr>");
			builder.append("<tr>");	
				builder.append("<td>");
					builder.append("number");
				builder.append("</td>");
				builder.append("<td>");
					builder.append(number);
				builder.append("</td>");
			builder.append("</tr>");
//		builder.append(nL + "lastOnline");
//		builder.append("\t" + 
//				((lastOnline != null)?
//						dateFormat.format(lastOnline)
//						: "Unknown")
//						);
			builder.append("<tr>");	
				builder.append("<td>");
					builder.append("power / >51");
				builder.append("</td>");
				builder.append("<td>");
					builder.append(Math.round(power) + 
						" / " + 
						Math.round(power51));
				builder.append("</td>");
			builder.append("</tr>");
		builder.append("</table>");
		builder.append(table());
		
		if(!playerSpecialAbilities.isEmpty())
		{
			builder.append("<tr><td colspan=\"3\">");
			builder.append(table());
			builder.append(
					"<tr" +
					"<td width=\"100%\"><hr size=1></td>" +
					"<td align=\"center\">"
					);
			builder.append("&nbsp;special&nbsp;abilities&nbsp;");
			builder.append(
					"</td>" +
					"<td width=\"100%\"><hr size=1></td>" +
					"</tr></table></td></tr>"
					);
			builder.append("<tr><td colspan=\"3\">");
			builder.append(table());
			for(Map.Entry<String, Integer> entry : 
				playerSpecialAbilities.entrySet())
			{
				builder.append("<tr><td>" + entry.getKey() + "</td>");
				builder.append("<td align=\"center\">");
				for(int i=0;i < entry.getValue();i++)
				{
					builder.append("<img src=\"" + star + "\"></img>");
				}
				builder.append("</td></tr>");
			}
			builder.append("</table></td></tr>");
		}
		
		for (int i = 0; i < attribs.length; i++) {
			
			if(	i == PHYSICAL ||
				i == MENTAL ||
				i == TECHNICAL ||
				i == FINISHING ||
				i == KEEPER)
			{
					builder.append("<tr><td colspan=\"3\">");
					builder.append(table());
					builder.append(
						"<tr" +
						"<td width=\"100%\"><hr size=1></td>" +
						"<td align=\"center\">&nbsp;"
						);
			}
			switch (i)
			{
			case PHYSICAL:
				builder.append("physical");
				break;
			case TECHNICAL:
				builder.append("technical");
				break;
			case MENTAL:
				builder.append("mental");
				break;
			case FINISHING:
				builder.append("finishing");
				break;
			case KEEPER:
				builder.append("keeper");
				break;
			default:
				break;
			}
			if(	i == PHYSICAL ||
				i == MENTAL ||
				i == TECHNICAL ||
				i == FINISHING ||
				i == KEEPER)
					builder.append(
						"&nbsp;</td>" +
						"<td width=\"100%\"><hr size=1></td>" +
						"</tr></table></td></tr>"
						);
			if(isMyChar())
				builder.append("<tr style=\"color:"
						+ attribs[i].getHtmlColor()
						+ "\">"
						+ "<td>"
						+ attribNames[i]
				        + "</td><td>"
						+ attribs[i].getDescription()
						+ "</td><td>"
						+ "<a style=\"color:"
						+ attribs[i].getHtmlColor()
						+ "\" href=\"" 
						+ (firstAttribID + i)
						+ "\">"
						+ attribs[i].getBounds()
						+ "</a>"
						+ "</td></tr>");
			else
				builder.append("<tr style=\"color:"
						+ attribs[i].getHtmlColor()
						+ "\">"
						+ "<td>"
						+ attribNames[i]
				        + "</td><td>"
						+ attribs[i].getDescription()
						+ "</td><td>"
						+ attribs[i].getBounds()
						+ "</td></tr>");
			
//			String hex = Integer.toHexString(attribs[i].getColor().getRGB());
//			hex = hex.substring(2);
//			System.out.println(hex.length());
//			builder.append(nL + "<font color=\"#"
//					+ hex
//					+ "\">"
//					+ attribs[i].getColor().getRGB() 
//					+ attribNames[i] 
//			        + " "
//					+ attribs[i]
//					+ "</font>");
			
		}
		builder.append("</table>");
		return builder.toString();
	}
	
	public Color getActivityColor()
	{
		Color c = null;
		switch (activity) {
		case ACTIVE:
			c = Color.GREEN.darker();
			break;
		case CASUAL:
			c = new Color(Integer.parseInt("E8BE00", 16));
			
			break;
		case INACTIVE:
			c = new Color(Integer.parseInt("FF6000", 16));
			break;
		default:
			c = Color.RED;
		}
		return c;
	}
	

	@Override
	public int compareTo(Player o) {
		int returnValue = -1;
		returnValue = positions.get(position).compareTo(
				positions.get(o.position));
		if(returnValue == 0)
			returnValue = birthDate.compareTo(o.birthDate);
		if(activity >= o.activity)
		{
			if(activity >= INACTIVE)
				returnValue = 1;
		}
		else
		{
			if(o.activity >= INACTIVE)
				returnValue = -1;
		}
//		if(activity != o.activity)
//		{
//			if(activity >= INACTIVE)
//				returnValue = 1;
//			else if(o.activity == INACTIVE)
//				returnValue = -1;
//		}
		return returnValue;
	}
	

}
